home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / progjrn / pj_vga.arc / VGA71-L1.ASM < prev    next >
Assembly Source File  |  1988-10-16  |  8KB  |  329 lines

  1. ;
  2. ; *** Listing 1 ***
  3. ;
  4. ; Program to demonstrate pixel drawing in 320x400 256-color
  5. ; mode on the VGA. Draws 8 lines to form an octagon, a pixel
  6. ; at a time. Draws 8 octagons in all, one on top of the other,
  7. ; each in a different color set. Although it's not used, a
  8. ; pixel read function is also provided.
  9. ;
  10. VGA_SEGMENT    equ    0a000h
  11. SC_INDEX    equ    3c4h    ;Sequence Controller Index register
  12. GC_INDEX    equ    3ceh    ;Graphics Controller Index register
  13. CRTC_INDEX    equ    3d4h    ;CRT Controller Index register
  14. MAP_MASK    equ    2    ;Map Mask register index in SC
  15. MEMORY_MODE    equ    4    ;Memory Mode register index in SC
  16. MAX_SCAN_LINE    equ    9    ;Maximum Scan Line reg index in CRTC
  17. START_ADDRESS_HIGH equ    0ch    ;Start Address High reg index in CRTC
  18. UNDERLINE    equ    14h    ;Underline Location reg index in CRTC
  19. MODE_CONTROL    equ    17h    ;Mode Control register index in CRTC
  20. READ_MAP    equ    4    ;Read Map register index in GC
  21. GRAPHICS_MODE    equ    5    ;Graphics Mode register index in GC
  22. MISCELLANEOUS    equ    6    ;Miscellaneous register index in GC
  23. SCREEN_WIDTH    equ    320    ;# of pixels across screen
  24. SCREEN_HEIGHT    equ    400    ;# of scan lines on screen
  25. WORD_OUTS_OK    equ    1    ;set to 0 to assemble for
  26.                 ; computers that can't handle
  27.                 ; word outs to indexed VGA registers
  28. ;
  29. stack    segment para stack 'STACK'
  30.     db    512 dup (?)
  31. stack    ends
  32. ;
  33. Data    segment    word 'DATA'
  34. ;
  35. BaseColor    db    0
  36. ;
  37. ; Structure used to control drawing of a line.
  38. ;
  39. LineControl    struc
  40. StartX        dw    ?
  41. StartY        dw    ?
  42. LineXInc    dw    ?
  43. LineYInc    dw    ?
  44. BaseLength    dw    ?
  45. LineColor    db    ?
  46. LineControl    ends
  47. ;
  48. ; List of descriptors for lines to draw.
  49. ;
  50. LineList    label    LineControl
  51.     LineControl    <130,110,1,0,60,0>
  52.     LineControl    <190,110,1,1,60,1>
  53.     LineControl    <250,170,0,1,60,2>
  54.     LineControl    <250,230,-1,1,60,3>
  55.     LineControl    <190,290,-1,0,60,4>
  56.     LineControl    <130,290,-1,-1,60,5>
  57.     LineControl    <70,230,0,-1,60,6>
  58.     LineControl    <70,170,1,-1,60,7>
  59.     LineControl    <-1,0,0,0,0,0>
  60. Data    ends
  61. ;
  62. ; Macro to output a word value to a port.
  63. ;
  64. OUT_WORD    macro
  65. if WORD_OUTS_OK
  66.     out    dx,ax
  67. else
  68.     out    dx,al
  69.     inc    dx
  70.     xchg    ah,al
  71.     out    dx,al
  72.     dec    dx
  73.     xchg    ah,al
  74. endif
  75.     endm
  76. ;
  77. ; Macro to output a constant value to an indexed VGA register.
  78. ;
  79. CONSTANT_TO_INDEXED_REGISTER    macro    ADDRESS, INDEX, VALUE
  80.     mov    dx,ADDRESS
  81.     mov    ax,(VALUE shl 8) + INDEX
  82.     OUT_WORD
  83.     endm
  84. ;
  85. Code    segment
  86.     assume    cs:Code, ds:Data
  87. Start    proc    near
  88.     mov    ax,Data
  89.     mov    ds,ax
  90. ;
  91. ; Set 320x400 256-color mode.
  92. ;
  93.     call    Set320By400Mode
  94. ;
  95. ; We're in 320x400 256-color mode. Draw each line in turn.
  96. ;
  97. ColorLoop:
  98.     mov    si,offset LineList ;point to the start of the
  99.                 ; line descriptor list
  100. LineLoop:
  101.     mov    cx,[si+StartX]    ;set the initial X coordinate
  102.     cmp    cx,-1
  103.     jz    LinesDone    ;a descriptor with a -1 X
  104.                 ; coordinate marks the end
  105.                 ; of the list
  106.     mov    dx,[si+StartY]       ;set the initial Y coordinate,
  107.     mov    bl,[si+LineColor]  ; line color,
  108.     mov    bp,[si+BaseLength] ; and pixel count
  109.     add    bl,[BaseColor]    ;adjust the line color according
  110.                 ; to BaseColor
  111. PixelLoop:
  112.     push    cx        ;save the coordinates
  113.     push    dx
  114.     call    WritePixel    ;draw this pixel
  115.     pop    dx        ;retrieve the coordinates
  116.     pop    cx
  117.     add    cx,[si+LineXInc] ;set the coordinates of the
  118.     add    dx,[si+LineYInc] ; next point of the line
  119.     dec    bp        ;any more points?
  120.     jnz    PixelLoop    ;yes, draw the next
  121.     add    si,size LineControl ;point to the next line descriptor
  122.     jmp    LineLoop    ; and draw the next line
  123. LinesDone:
  124.     call    GetNextKey    ;wait for a key, then
  125.     inc    [BaseColor]    ; bump the color selection and
  126.     cmp    [BaseColor],8    ; see if we're done
  127.     jb    ColorLoop    ;not done yet
  128. ;
  129. ; Wait for a key and return to text mode and end when
  130. ; one is pressed.
  131. ;
  132.     call    GetNextKey
  133.     mov    ax,0003h
  134.     int    10h    ;text mode
  135.     mov    ah,4ch
  136.     int    21h    ;done
  137. ;
  138. Start    endp
  139. ;
  140. ; Sets up 320x400 256-color modes.
  141. ;
  142. ; Input: none
  143. ;
  144. ; Output: none
  145. ;
  146. Set320By400Mode    proc    near
  147. ;
  148. ; First, go to normal 320x200 256-color mode, which is really a
  149. ; 320x400 256-color mode with each line scanned twice.
  150. ;
  151.     mov    ax,0013h  ;AH = 0 means mode set, AL = 13h selects
  152.             ; 256-color graphics mode
  153.     int    10h    ;BIOS video interrupt
  154. ;
  155. ; Change CPU addressing of video memory to linear (not odd/even,
  156. ; chain, or chain 4), to allow us to access all 256K of display
  157. ; memory. When this is done, VGA memory will look just like memory
  158. ; in modes 10h and 12h, except that each byte of display memory will
  159. ; control one 256-color pixel, with 4 adjacent pixels at any given
  160. ; address, one pixel per plane.
  161. ;
  162.     mov    dx,SC_INDEX
  163.     mov    al,MEMORY_MODE
  164.     out    dx,al
  165.     inc    dx
  166.     in    al,dx
  167.     and    al,not 08h    ;turn off chain 4
  168.     or    al,04h        ;turn off odd/even
  169.     out    dx,al
  170.     mov    dx,GC_INDEX
  171.     mov    al,GRAPHICS_MODE
  172.     out    dx,al
  173.     inc    dx
  174.     in    al,dx
  175.     and    al,not 10h    ;turn off odd/even
  176.     out    dx,al
  177.     dec    dx
  178.     mov    al,MISCELLANEOUS
  179.     out    dx,al
  180.     inc    dx
  181.     in    al,dx
  182.     and    al,not 02h    ;turn off chain
  183.     out    dx,al
  184. ;
  185. ; Now clear the whole screen, since the mode 13h mode set only
  186. ; cleared 64K out of the 256K of display memory. Do this before
  187. ; we switch the CRTC out of mode 13h, so we don't see garbage
  188. ; on the screen when we make the switch.
  189. ;
  190.     CONSTANT_TO_INDEXED_REGISTER SC_INDEX,MAP_MASK,0fh
  191.                 ;enable writes to all planes, so
  192.                 ; we can clear 4 pixels at a time
  193.     mov    ax,VGA_SEGMENT
  194.     mov    es,ax
  195.     sub    di,di
  196.     mov    ax,di
  197.     mov    cx,8000h    ;# of words in 64K
  198.     cld
  199.     rep    stosw        ;clear all of display memory
  200. ;
  201. ; Tweak the mode to 320x400 256-color mode by not scanning each
  202. ; line twice.
  203. ;
  204.     mov    dx,CRTC_INDEX
  205.     mov    al,MAX_SCAN_LINE
  206.     out    dx,al
  207.     inc    dx
  208.     in    al,dx
  209.     and    al,not 1fh    ;set maximum scan line = 0
  210.     out    dx,al
  211.     dec    dx
  212. ;
  213. ; Change CRTC scanning from doubleword mode to byte mode, allowing
  214. ; the CRTC to scan more than 64K of video data.
  215. ;
  216.     mov    al,UNDERLINE
  217.     out    dx,al
  218.     inc    dx
  219.     in    al,dx
  220.     and    al,not 40h    ;turn off doubleword
  221.     out    dx,al
  222.     dec    dx
  223.     mov    al,MODE_CONTROL
  224.     out    dx,al
  225.     inc    dx
  226.     in    al,dx
  227.     or    al,40h    ;turn on the byte mode bit, so memory is
  228.             ; scanned for video data in a purely
  229.             ; linear way, just as in modes 10h and 12h
  230.     out    dx,al
  231.     ret
  232. Set320By400Mode    endp
  233. ;
  234. ; Draws a pixel in the specified color at the specified
  235. ; location in 320x400 256-color mode.
  236. ;
  237. ; Input:
  238. ;    CX = X coordinate of pixel
  239. ;    DX = Y coordinate of pixel
  240. ;    BL = pixel color
  241. ;
  242. ; Output: none
  243. ;
  244. ; Registers altered: AX, CX, DX, DI, ES
  245. ;
  246. WritePixel    proc    near
  247.     mov    ax,VGA_SEGMENT
  248.     mov    es,ax    ;point to display memory
  249.     mov    ax,SCREEN_WIDTH/4
  250.             ;there are 4 pixels at each address, so
  251.             ; each 320-pixel row is 80 bytes wide
  252.             ; in each plane
  253.     mul    dx    ;point to start of desired row
  254.     push    cx    ;set aside the X coordinate
  255.     shr    cx,1    ;there are 4 pixels at each address
  256.     shr    cx,1    ; so divide the X coordinate by 4
  257.     add    ax,cx    ;point to the pixel's address
  258.     mov    di,ax
  259.     pop    cx    ;get back the X coordinate
  260.     and    cl,3    ;get the plane # of the pixel
  261.     mov    ah,1
  262.     shl    ah,cl    ;set the bit corresponding to the plane
  263.             ; the pixel is in
  264.     mov    al,MAP_MASK
  265.     mov    dx,SC_INDEX
  266.     OUT_WORD    ;set to write to the proper plane for
  267.             ; the pixel
  268.     mov    es:[di],bl    ;draw the pixel
  269.     ret
  270. WritePixel    endp
  271. ;
  272. ; Reads the color of the pixel at the specified location in 320x400
  273. ; 256-color mode.
  274. ;
  275. ; Input:
  276. ;    CX = X coordinate of pixel to read
  277. ;    DX = Y coordinate of pixel to read
  278. ;
  279. ; Output:
  280. ;    AL = pixel color
  281. ;
  282. ; Registers altered: AX, CX, DX, SI, ES
  283. ;
  284. ReadPixel    proc    near
  285.     mov    ax,VGA_SEGMENT
  286.     mov    es,ax    ;point to display memory
  287.     mov    ax,SCREEN_WIDTH/4
  288.             ;there are 4 pixels at each address, so
  289.             ; each 320-pixel row is 80 bytes wide
  290.             ; in each plane
  291.     mul    dx    ;point to start of desired row
  292.     push    cx    ;set aside the X coordinate
  293.     shr    cx,1    ;there are 4 pixels at each address
  294.     shr    cx,1    ; so divide the X coordinate by 4
  295.     add    ax,cx    ;point to the pixel's address
  296.     mov    si,ax
  297.     pop    ax    ;get back the X coordinate
  298.     and    al,3    ;get the plane # of the pixel
  299.     mov    ah,al
  300.     mov    al,READ_MAP
  301.     mov    dx,GC_INDEX
  302.     OUT_WORD    ;set to read from the proper plane for
  303.             ; the pixel
  304.     lods    byte ptr es:[si] ;read the pixel
  305.     ret
  306. ReadPixel    endp
  307. ;
  308. ; Waits for the next key and returns it in AX.
  309. ;
  310. ; Input: none
  311. ;
  312. ; Output:
  313. ;    AX = full 16-bit code for key pressed
  314. ;
  315. GetNextKey    proc    near
  316. WaitKey:
  317.     mov    ah,1
  318.     int    16h
  319.     jz    WaitKey    ;wait for a key to become available
  320.     sub    ah,ah
  321.     int    16h    ;read the key
  322.     ret
  323. GetNextKey    endp
  324. ;
  325. Code    ends
  326. ;
  327.     end    Start
  328.  
  329.